﻿
using LightCAD.MathLib;
using System.Collections.Generic;
using System.Net;

namespace LightCAD.Core.Elements
{
    public class LcEllipse : LcCurve2d
    {
        public Vector2 Center { get => this.Ellipse.Center; set => this.Ellipse.Center = value; }
        public Vector2 AxisX
        {
            [MethodImpl((MethodImplOptions)768)]
            get;

        }
            = Vector2.UnitX;
        public double Rotation
        {
            get => this.Ellipse.Rotation;
            set
            {
                this.Ellipse.Rotation = value;
                this.AxisX.Set(1, 0).RotateAround(0, 0, value);
            }
        }
        public double RadiusX { get => this.Ellipse.RadiusX; set => this.Ellipse.RadiusX = value; }
        public double RadiusY { get => this.Ellipse.RadiusY; set => this.Ellipse.RadiusY = value; }
        public double StartAngle { get => this.Ellipse.StartAngle; set => this.Ellipse.StartAngle = value; }
        public double EndAngle { get => this.Ellipse.EndAngle; set => this.Ellipse.EndAngle = value; }
        public bool IsClockwise { get => this.Ellipse.IsClockwise; set => this.Ellipse.IsClockwise = value; }
        public Ellipse2d Ellipse => this.Curve as Ellipse2d;
        public LcEllipse()
        {
            this.Curve = new Ellipse2d();
            this.StartAngle = 0;
            this.EndAngle = Utils.TwoPI;
            this.Type = BuiltinElementType.Ellipse;
        }
        public LcEllipse(Vector2 center, double radiusX, double radiusY, double rotation, double startAngle = 0, double endAngle = Utils.TwoPI) : this()
        {
            this.Center = center;
            this.Rotation = rotation;
            this.RadiusX = radiusX;
            this.RadiusY = radiusY;
            this.StartAngle = startAngle;
            this.EndAngle = endAngle;
            this.IsClockwise = false;
        }


        public override LcElement Clone()
        {
            var clone = new LcEllipse();
            clone.Copy(this);
            return clone;
        }

        public override void WriteProperties(Utf8JsonWriter writer, JsonSerializerOptions soptions)
        {
            base.WriteProperties(writer, soptions);
            writer.WriteVector2dProperty(nameof(this.Center), this.Center);
            writer.WriteVector2dProperty(nameof(this.AxisX), this.AxisX);
            writer.WriteNumberProperty(nameof(this.RadiusX), this.RadiusX);
            writer.WriteNumberProperty(nameof(this.RadiusY), this.RadiusY);
            writer.WriteNumberProperty(nameof(this.StartAngle), this.StartAngle);
            writer.WriteNumberProperty(nameof(this.EndAngle), this.EndAngle);
        }


        public override void ReadProperties(ref JsonElement jele)
        {
            base.ReadProperties(ref jele);
            this.Center = jele.ReadVector2dProperty(nameof(this.Center));
            this.Rotation = jele.ReadDoubleProperty(nameof(this.Rotation));
            this.RadiusX = jele.ReadDoubleProperty(nameof(this.RadiusX));
            this.RadiusY = jele.ReadDoubleProperty(nameof(this.RadiusY));
            this.StartAngle = jele.ReadDoubleProperty(nameof(this.StartAngle));
            this.EndAngle = jele.ReadDoubleProperty(nameof(this.EndAngle));
        }
        public static Matrix3 matrix3;
        public static double Scale;
        public override List<Vector2> GetCrossVectorByLine(Line2d line2D)
        {
            //matrix3 = Matrix3.RotateInRadian(0-this.Ellipse.Rotation, this.Ellipse.Center);
            // List<Vector2> points = GeoUtils.CrossEllipseLine(matrix3.MultiplyPoint(this.Ellipse.Center), this.Ellipse.RadiusX, this.Ellipse.RadiusY , matrix3.MultiplyPoint(line2D.Start), matrix3.MultiplyPoint(line2D.End));
             List<Vector2> points = GeoUtils.CrossEllipseLine(this.Ellipse.Rotation, this.Ellipse.Center, this.Ellipse.RadiusX , this.Ellipse.RadiusY, line2D.Start, line2D.End);
            //if (points != null)
            //{
            //    List<Vector2> rps = new List<Vector2>();
            //    Matrix3 sctow = Matrix3.RotateInRadian(this.Ellipse.Rotation, this.Ellipse.Center);
            //    foreach (var item in points)
            //    {
            //        rps.Add(sctow.MultiplyPoint(item));
            //    }
            //    return rps;
            //}
            //else
            return points;
        }

        public override List<Vector2> GetCrossVectorByArc(Arc2d arc2D)
        {
            //List<Vector2> points = GeoUtils.EllipseCrossArc(this.Ellipse, arc2D, 0.05);
            return null;
        }

        public override void Copy(LcElement src)
        {
            var ellipse = ((LcEllipse)src);
            this.Center = ellipse.Center;
            this.Rotation = ellipse.Rotation;
            this.RadiusX = ellipse.RadiusX;
            this.RadiusY = ellipse.RadiusY;
            this.StartAngle = ellipse.StartAngle;
            this.EndAngle = ellipse.EndAngle;
        }

        public void Set(Vector2 center = null, double? Rotation = null, double? radiusX = null, double? radiusY = null, double? startAngle = null, double? endAngle = null, bool fireChangedEvent = false)
        {
            bool chg_center = (center != null && center != this.Center);
            bool df = false;
            if (chg_center)    //如果是圆心
            {

                OnPropertyChangedBefore(nameof(Center), this.Center, center);
                var oldValue = this.Center;
                this.Center = center;
                OnPropertyChangedAfter(nameof(Center), oldValue, this.Center);
            }

            bool chg_top = (radiusY != null && radiusY != this.RadiusY);
            if (chg_top)
            {
                OnPropertyChangedBefore(nameof(RadiusY), this.RadiusY, RadiusY);
                var oldValue = this.RadiusY;
                this.RadiusY = radiusY.Value;
                OnPropertyChangedAfter(nameof(RadiusY), oldValue, this.RadiusY);
            }

            bool chg_left = (radiusX != null && radiusX != this.RadiusX);
            if (chg_left)
            {
                OnPropertyChangedBefore(nameof(RadiusX), this.RadiusX, RadiusX);
                var oldValue = this.RadiusX;
                this.RadiusX = radiusX.Value;
                OnPropertyChangedAfter(nameof(RadiusX), oldValue, this.RadiusX);
            }


        }
    }
}
